/*
 * @Author: wangwei wwdqq7@qq.com
 * @Date: 2025-03-31 17:03:00
 * @LastEditors: wangwei wwdqq7@qq.com
 * @LastEditTime: 2025-04-01 22:26:20
 * @FilePath: /FullStack/pro/typeorm-mysql/src/main.ts
 * @Description: --
 */
import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  UnauthorizedException,
  ValidationPipe,
} from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { Request, Response } from 'express';

import { AppModule } from '@/app.module';

@Catch(UnauthorizedException)
class JwtAuthExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message: '认证失败：无效的JWT令牌或令牌已过期，请重新登录',
    });
  }
}

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // 全局管道，用于请求验证
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true, // 过滤掉未定义的属性
      transform: true, // 自动转换类型
      forbidNonWhitelisted: true, // 禁止未定义的属性
    }),
  );

  // 全局异常过滤器，用于处理JWT认证失败的情况
  app.useGlobalFilters(new JwtAuthExceptionFilter());

  // 允许跨域
  app.enableCors();

  // 全局前缀
  app.setGlobalPrefix('api/v1');

  // Swagger配置
  const config = new DocumentBuilder()
    .setTitle('用户权限管理系统API')
    .setDescription('提供用户管理、角色管理、权限管理等相关接口')
    .setVersion('1.0.0')
    .addBearerAuth(
      {
        type: 'http',
        scheme: 'bearer',
        bearerFormat: 'JWT',
        name: 'JWT',
        description: '输入JWT token',
        in: 'header',
      },
      'jwt', // 这个名称用于在控制器中引用
    )
    .addTag('用户管理', '用户的增删改查操作')
    .addTag('角色管理', '角色的增删改查操作')
    .addTag('权限管理', '权限的增删改查操作')
    .addTag('菜单管理', '菜单的增删改查操作')
    .addTag('认证管理', '用户的登录认证')

    // .addServer('/api/v1')
    .build();

  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('docs', app, document, {
    swaggerOptions: {
      persistAuthorization: true, // 保持授权状态
      docExpansion: 'none', // 默认折叠所有接口
      filter: true, // 启用过滤
      showExtensions: true, // 显示扩展信息
    },
  });

  await app.listen(3000);
  console.log(`应用已启动: http://localhost:3000/docs`);
}
bootstrap().then(() => console.log('应用已关闭'));
